home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
101_01
/
nlife.c
< prev
next >
Wrap
Text File
|
1985-11-13
|
7KB
|
273 lines
/* Yet another LIFE simulator 9/14/80 Steve Ward
* Uses H19 graphics, 25th line to give a 50x80 field.
* Usage:
* life <filename> default is "life.dat"
*
* Commands:
* CURSOR MOTION: ^F, ^N, ^P, ^H, TAB, RETURN, keypad arrows, 0.
* SET POINTS: period, keypad 5 (XORs)
* DELETE: DELETE key.
* SAVE: A-Z save relative to cursor in one of 26 slots.
* GET: a-z fetch (XOR) relative to cursor.
* MISC: ^X write out A-Z slots in file and exit.
* ^C quit, no file output.
* ENTER (keypad): step one simulation step.
* LINEFEED: run until character typed.
* ^L redisplay screen.
* ^Z clear LIFE space.
* KEY 9: Rotate about cursor
* KEY 7: Flip about cursor
* KEY 1: Random 5x5 configuration around cursor
* KEY 3: Random 10x10 configuration around cursor
*
* N.B: Left/right, top/bottom edges of 50x80 field are adjacent.
*/
#define XSIZE 80 /* Horizontal size */
#define YSIZE 50 /* Vertical size */
#define LIVE 0x10 /* Live cell flag. */
int LStep(); /* Assy-lang update routine. */
int Fixup();
int Forall();
int CurX, CurY; /* Current cell coordinates. */
char DpyX, DpyY; /* Current (raw) display coordinates */
char *row[YSIZE]; /* ptrs to each row. */
int Rand1, Rand2, Rand3; /* Random number seeds */
char RanFlag; /* Flag: initialize randoms */
struct {
char bits[(XSIZE*YSIZE)/8]; } Memory[27];
char space[XSIZE*YSIZE]; /* the universe matrix */
MoveTo(x,y)
{ puts("\033Y"); putchar(y+32); putchar(x+32); }
Split()
{ puts("\033z"); exit(); }
/* Update a point on the screen: assumes graphics mode.
*/
Updpy(x, y)
{ char key, dpyy;
dpyy = y & 0xFE;
MoveTo(x, dpyy>>1);
key = (((LIVE & (row[dpyy | 1])[x]))? 2:0) |
(((LIVE & (row[dpyy])[x]))? 1 : 0);
switch(key) {
case 0: ReVid(0); key = ' '; break;
case 3: ReVid(1); key = ' '; break;
case 1: ReVid(0); key = 'p'; break;
case 2: ReVid(1); key = 'p'; break; }
putchar(key); }
/* Change a cell contents:
*/
CCell(x, y)
{ Updpy(x, y); }
/* Set/clear reverse video mode:
*/
ReVid(flag)
{ puts((flag != 0)? "\033p" : "\033q"); }
/*
Blink the cursor, waiting for input, and return whatever
was typed:
*/
int Blink()
{ char *it, save, i; int delay;
it = (row[CurY])+CurX;
save = *it;
for (;;i++)
{ switch (i &= 3)
{ case 0: *it = 0; break;
case 2: *it = LIVE; break;
case 1:
case 3: *it = save; break; }
Updpy(CurX, CurY);
for (delay=200; delay--; Rand1++)
if (kbhit()) { i = getchar();
*it = save; Updpy(CurX, CurY); RanFlag=1;
return i; }}}
Move(dx, dy)
{ if ((CurX += dx) >= XSIZE) CurX = 0;
if (CurX < 0) CurX = XSIZE-1;
if ((CurY += dy) >= YSIZE) CurY = 0;
if (CurY < 0) CurY = YSIZE-1; }
/* Put a random n by n configuration at cursor:
*/
RandConf(n)
{ char x,y,i,j;
x = CurX-(n>>1);
y = CurY-(n>>1);
if (RanFlag) nrand(-1, Rand1, Rand2, Rand3); Rand3=Rand2; Rand2=Rand1;
RanFlag=0;
for (j=0; j<=n; j++)
for (i=0; i<=n; i++) if (!(nrand(1) & 0x30))
{ (row[j+y])[i+x] ^= LIVE; UpDpy(i+x,j+y); }}
Edit()
{ char ch, *cc;
CurX = XSIZE>>1;
CurY = YSIZE>>1;
puts("\033F");
for (;;)
{ switch(ch = Blink())
{ case '.':
case '.': (row[CurY])[CurX] = LIVE;
Updpy(CurX++, CurY);
case ' ':
case '6':
case 'F'-64: Move(1,0); continue;
case '4':
case 'H'-64: Move(-1,0); continue;
case '7': Flip(); continue;
case '9': Rotate(); continue;
case 'X'-64: return;
case '5': (row[CurY])[CurX] ^= LIVE; continue;
case 0177: Move(-1,0);
(row[CurY])[CurX] = 0;
Updpy(CurX, CurY); continue;
case '\r': CurX = 0; Move(0,1); continue;
case '8':
case 'P'-64: Move(0,-1); continue;
case '2':
case 'N'-64: Move(0,1); continue;
case '\n': while (!kbhit()) LStep(space); continue;
case '\\': while (1) { ch = 100; RandConf(5);
while (ch--)
{ if (kbhit()) goto endit;
LStep(space); }}
endit: continue;
case 'Z'-64: clear(); continue;
case 'L'-64: display(); continue;
case 'C'-64: Split();
case '\t': CurX = (CurX + 8) & 0xF8;
Move(0,0); continue;
case '/': LStep(space); continue;
case '0': if (CurX|CurY) CurX = CurY = 0;
else { CurX=(XSIZE>>1); CurY=(YSIZE>>1); }
continue;
case '1': RandConf(5); continue;
case '3': RandConf(10); continue;
default: if ((ch >= 'a') && (ch <= 'z'))
{ Unsave(&(Memory[ch-'a'])); continue; }
if ((ch >= 'A') && (ch <= 'Z'))
{ Save(&(Memory[ch-'A'])); continue; }
putchar(7); continue;
}}
}
main(argc,argv)
char **argv;
{ char *cc, x, y, *name;
int FileSize, fileid;
FileSize = (26*(XSIZE/8)*YSIZE + 127) >> 7; /* File size, in blocks */
setmem(Memory, 26*(XSIZE/8)*YSIZE, 0);
fileid = -1;
name = "life.dat";
if (argc > 1) name = argv[1];
if ((fileid = open(name, 2)) == -1)
{ puts("Creating file "); puts(name); puts("\r\n");
fileid = creat(name); }
else { seek(fileid,0,0); read(fileid, Memory, FileSize); }
cc = space;
for (y=0; y<YSIZE; y++)
{ row[y] = cc; cc += XSIZE; }
puts("\033x1\033x5");
clear();
Edit();
if (fileid != -1)
{ seek(fileid,0,0); write(fileid, Memory, FileSize); close(fileid); }
Split(); }
clear()
{ puts("\033H\033J\033Y8 \033K");
setmem(space,(XSIZE*YSIZE),0);
CurX = (XSIZE>>1); CurY = (YSIZE>>1); }
/* Display the current generation */
display()
{ char x, y, *cc;
cc = space;
puts("\033F\033Y8 \033K\033H\033J");
for (y=0; y<YSIZE; y += 2)
{ for (x=0; x<XSIZE; x++, cc++)
if ((*cc | (cc[XSIZE])) & LIVE) Updpy(x,y);
cc += XSIZE; }}
Unsave(where)
char *where;
{ char *p, bit, x, y;
bit = 0; where--; y = CurY;
do { p = row[y] + (x = CurX);
do { if (!(bit <<= 1)) { bit = 1; where++; }
if (bit & *where) { *p ^= LIVE; Updpy(x,y); }
p++;
if (++x == XSIZE) { x = 0; p = row[y]; }
} while (x != CurX);
if (++y == YSIZE) y = 0;
} while (y != CurY); }
Save(where)
char *where;
{ char *p, bit, x, y;
bit = 0; where--; y = CurY;
do { p = row[y] + (x = CurX);
do { if (!(bit <<= 1)) { bit = 1; *++where = 0; }
if (*p) *where |= bit;
p++;
if (++x == XSIZE) { x = 0; p = row[y]; }
} while (x != CurX);
if (++y == YSIZE) y = 0;
} while (y != CurY); }
char *Cell();
Rot1(x,y)
{ *Cell(space, CurX+CurY-y, CurY+x-CurX) |= (LIVE>>1); }
Rotate()
{ Forall(space, &Rot1); Fixup(space); }
Flip1(x,y)
{ *Cell(space, CurX+y-CurY, CurY+x-CurX) |= (LIVE>>1); }
Flip()
{ Forall(space, &Flip1); Fixup(space); }
getchar()
{
char c;
return bios(3);
}
putchar(c)
char c;
{
return bios(4,c);
}
kbhit()
{
return bios(2);
}